package com.zhuoyue.biz.core.api.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zhuoyue.biz.core.api.dao.EzvizTokenDao;
import com.zhuoyue.biz.core.api.domain.*;
import com.zhuoyue.biz.core.api.dto.rep.ChildAccountMessageRepDTO;
import com.zhuoyue.biz.core.api.service.JpushService;
import com.zhuoyue.common.constant.ExtrasCode;
import com.zhuoyue.common.constant.MessageCode;
import com.zhuoyue.common.constant.UserConstant;
import com.zhuoyue.common.dto.BaseResultDTO;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zhuoyue.biz.core.api.dao.AppUserHomeRelationDao;
import com.zhuoyue.biz.core.api.dao.AppUserHomeRelationViewDao;
import com.zhuoyue.common.constant.ResultCode;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author wjming
 * @ClassName: AppUserHomeRelationService
 * @Description: 用户与家庭之间的关系服务类
 * 注意，此类不可以使用userService和homeService 否则会有异常
 * The dependencies of some of the beans in the application context form a cycle:
 * @Date 2021-07-02 16:56
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AppUserHomeRelationService extends ServiceImpl<AppUserHomeRelationDao, AppUserHomeRelationDO> {
    private Gson gson = new Gson();

    private final AppUserHomeRelationViewDao appUserHomeRelationViewDao;

    private final AppUserHomeRelationDao appUserHomeRelationDao;
    private final EzvizTokenDao ezvizTokenDao;

    private final JpushService jPushService;

    /**
     * 主人取消
     */
    private static final String MASTER_CANCEL_SHARE = "0";
    /**
     * 子账号自己取消
     */
    private static final String CHILD_ACCOUNT_CANCEL_SHARE = "1";

    public List<AppUserHomeRelationViewDO> getRelationSpeakByAppUserId(String appUserId) {
        List<AppUserHomeRelationViewDO> list = appUserHomeRelationViewDao
                .selectRelationSpeakByAppUserId(appUserId);
        if (list == null || CollectionUtils.isEmpty(list)) {
            throw new ZyServerException(ErrorType.result_not_exist.getCode(), "用户数据为空");
        }
        return list;
    }


    /**
     * 修改我的若琪和声必可
     * @param voiceType
     * @param selectStr
     * @param noSelectStr
     * @return
     */
    public BaseResultDTO updateSpeechCipheringEquipment(int voiceType,
                                                        String selectStr, String noSelectStr) {
        boolean resultVerification = true;
        BaseResultDTO result = new BaseResultDTO();

        List<String> selectList = gson.fromJson(selectStr, new TypeToken<List<String>>() {
        }.getType());
        List<String> noSelectList = gson.fromJson(noSelectStr, new TypeToken<List<String>>() {
        }.getType());
        AppUserHomeRelationDO relation = null;
        try {
            switch (voiceType) {
                // 修改我的若琪家庭设置
                case 0:
                    if (selectList != null && selectList.size() > 0) {
                        for (int i = 0; i < selectList.size(); i++) {
                            relation = new AppUserHomeRelationDO();
                            relation.setId(selectList.get(i) + "");
                            relation.setIsRokid(1);
                            appUserHomeRelationDao.updateRokid(relation);
                        }
                    }
                    if (noSelectList != null && noSelectList.size() > 0) {
                        for (int i = 0; i < noSelectList.size(); i++) {
                            relation = new AppUserHomeRelationDO();
                            relation.setId(noSelectList.get(i) + "");
                            relation.setIsRokid(0);
                            appUserHomeRelationDao.updateRokid(relation);
                        }
                    }
                    break;

                //修改我的声必可
                case 1:
                    if (selectList != null && selectList.size() > 0) {
                        for (int i = 0; i < selectList.size(); i++) {
                            relation = new AppUserHomeRelationDO();
                            relation.setId(selectList.get(i) + "");
                            relation.setIsAISpeak(1);
                            appUserHomeRelationDao.updateAiSpeaker(relation);
                        }
                    }
                    if (noSelectList != null && noSelectList.size() > 0) {
                        for (int i = 0; i < noSelectList.size(); i++) {
                            relation = new AppUserHomeRelationDO();
                            relation.setId(noSelectList.get(i) + "");
                            relation.setIsAISpeak(0);
                            appUserHomeRelationDao.updateAiSpeaker(relation);
                        }
                    }
                    break;

                //修改我的小度
                case 2:
                    if (selectList != null && selectList.size() > 0) {
                        for (int i = 0; i < selectList.size(); i++) {
                            relation = new AppUserHomeRelationDO();
                            relation.setId(selectList.get(i) + "");
                            relation.setIsDueros(1);
                            appUserHomeRelationDao.updateDuerOs(relation);
                        }
                    }
                    if (noSelectList != null && noSelectList.size() > 0) {
                        for (int i = 0; i < noSelectList.size(); i++) {
                            relation = new AppUserHomeRelationDO();
                            relation.setId(noSelectList.get(i) + "");
                            relation.setIsDueros(0);
                            appUserHomeRelationDao.updateDuerOs(relation);
                        }
                    }
                    break;

                case 3:
                    if (selectList != null && selectList.size() > 0) {
                        for (int i = 0; i < selectList.size(); i++) {
                            relation = new AppUserHomeRelationDO();
                            relation.setId(selectList.get(i) + "");
                            relation.setIsTmall(1);
                            ;
                            appUserHomeRelationDao.updateTmall(relation);
                        }
                    }

                    if (noSelectList != null && noSelectList.size() > 0) {
                        for (int i = 0; i < noSelectList.size(); i++) {
                            relation = new AppUserHomeRelationDO();
                            relation.setId(noSelectList.get(i) + "");
                            relation.setIsTmall(0);
                            appUserHomeRelationDao.updateTmall(relation);
                        }
                    }
                    break;

                default:
                    resultVerification = false;
                    break;
            }

            if (!resultVerification) {
                result.setSuccess(false);
                result.setResultCode(ResultCode.NO_DATA);
                result.setErrorDetail("无法识别当前类型");
                return result;
            }
            result.setSuccess(true);
            result.setResultCode(ResultCode.SUCCESS);

        } catch (Exception e) {
            log.error(
                    "AppUserHomeRelationServiceImpl call getChildUserList error ==== ",
                    e);
            result.setSuccess(false);
            result.setResultCode(ResultCode.SYS_ERROR);
            result.setErrorDetail("查询系统异常！");
        }
        return result;
    }

    /**
     * 添加家庭关系信息
     *
     * @param home
     */
    public void saveUserAndHomeRelation(HomeDO home, String appUserId) {
        AppUserHomeRelationDO relation = new AppUserHomeRelationDO().addMasterRelation(appUserId, home.getId());
        boolean save = save(relation);
        if (!save) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND);
        }
    }

    /**
     * 创建子账号的实现类:
     * 1:验证子账号是否注册
     * 2:确认是否可以分享
     * 3:确认分享成功
     * 4:获取主人家庭名称
     * 5:获取主人昵称
     * 6:给子账号发送已经分享的推送
     *
     * @param masterId         主人的ID
     * @param masterHomeId     主人的家庭ID
     * @param childAccount     被分享者的账号
     * @param organizationCode APP组织编码
     */
    public void createChildAccount(String masterId, String masterHomeId, String childAccount, String organizationCode) {
        AppUserDO childMessage = checkAccountIsRegister(childAccount, organizationCode);

        confirmCanShareToChildAccount(masterId, childMessage.getId(), masterHomeId);

        confirmShareMasterHomeToChildAccountSuccess(masterHomeId, childMessage.getId());

        String masterHomeName = appUserHomeRelationDao.getHomeNameById(masterHomeId);

        String masterName = appUserHomeRelationDao.getUserName(masterId);

        shareHomeJpushToChildAccount(masterName, masterHomeName, masterHomeId, childMessage.getSourceId(), childMessage.getId(),
                childMessage.getSourceType() + "", organizationCode);
    }

    /**
     * 取消分享:
     * 1:验证子账号是否注册
     * 2:删除分享关系信息
     * 3:向主人或者子账号发出取消推送
     *
     * @param homeId
     * @param childAccount
     * @param orgCode
     * @return
     */
    public void cancelShare(String homeId, String childAccount, String orgCode, String masterOrSelf) {
        AppUserDO childMessage = checkAccountIsRegister(childAccount, orgCode);
        removeShareRelation(childMessage.getId(), homeId);
        cancelShareJpush(childMessage, homeId, childAccount, orgCode, masterOrSelf);
    }

    /**
     * 转移家庭
     * 1:验证子账号是否注册
     * 2:只有一个家庭无法转移
     * 3:判断该家庭是否是分享家庭验证
     * 4:转移摄像头
     * 5:删除该家庭下所有所有分享过的家庭
     * 6:确认是否转移成功
     * 7:转移成功推送
     *
     * @param transferAccount
     * @param appUserHomeRelationDO
     * @param orgCode
     */
    @Transactional(rollbackFor = Exception.class)
    public void transferHome(String transferAccount, AppUserHomeRelationDO appUserHomeRelationDO, String orgCode) {
        String masterId = appUserHomeRelationDO.getAppUserId();
        String masterHomeId = appUserHomeRelationDO.getHomeId();

        AppUserDO childMessage = checkAccountIsRegister(transferAccount, orgCode);
        onlyOneHomeCanNotTransfer(masterId);
        AppUserHomeRelationDO masterHomeRelation = shareHomeCanNotHandle(masterId, masterHomeId);
        transferEz(childMessage.getId(), masterHomeId);
        removeMasterHomeShareRelation(masterHomeId);
        confirmTransferHomeToChildAccountSuccess(childMessage.getId(), masterHomeRelation.getId());
        transferHomeJpush(childMessage, appUserHomeRelationDO);
    }


    /**
     * 确认是否转移成功
     *
     * @param childId
     * @param relationId
     */
    private void confirmTransferHomeToChildAccountSuccess(String childId, String relationId) {
        AppUserHomeRelationDO relationDO = new AppUserHomeRelationDO();
        relationDO.setAppUserId(childId);
        relationDO.setId(relationId);
        boolean b = updateById(relationDO);
        if (!b) {
            throw new ZyServerException(ErrorType.Service_Fail.getCode(), "转移失败");
        }
        return;
    }

    /**
     * 删除该家庭下所有的分享信息
     *
     * @param masterHomeId
     */
    private void removeMasterHomeShareRelation(String masterHomeId) {
        LambdaQueryWrapper<AppUserHomeRelationDO> selectEq = Wrappers.<AppUserHomeRelationDO>lambdaQuery()
                .eq(AppUserHomeRelationDO::getHomeId, masterHomeId)
                .eq(AppUserHomeRelationDO::getRelationType, UserConstant.AppUserHomeRelation.SHARE);
        Integer integer = appUserHomeRelationDao.selectCount(selectEq);
        if (integer > 0) {
            int delete = appUserHomeRelationDao.delete(selectEq);
            if (delete < 1) {
                log.info("ransferHome->removeMasterHomeShareRelation 删除分享家庭失败 家庭ID:{masterHomeId}", masterHomeId);
                throw new ZyServerException(ErrorType.Service_Fail);
            }
        }
        return;
    }


    /**
     * 判断是否已经分享过该用户一次，如果已经分享过提示已分享
     *
     * @param childAccountId
     * @param masterHomeId
     */
    private void confirmCanShareToChildAccount(String masterId, String childAccountId, String masterHomeId) {
        QueryWrapper<AppUserHomeRelationDO> appUserHomeRelationDO = new QueryWrapper<>();
        appUserHomeRelationDO.eq("app_user_id", childAccountId);
        appUserHomeRelationDO.eq("home_id", masterHomeId);
        appUserHomeRelationDO.eq("relation_type", UserConstant.AppUserHomeRelation.SHARE);
        AppUserHomeRelationDO userHomeObj = appUserHomeRelationDao.selectOne(appUserHomeRelationDO);
        if (userHomeObj != null) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "该子账号与此家庭已经是分享关系");
        }
        shareHomeCanNotHandle(masterId, masterHomeId);
    }

    /**
     * 子账号无法进行分享过来的家庭进行分享或转移
     *
     * @param masterId
     * @param masterHomeId
     */
    private AppUserHomeRelationDO shareHomeCanNotHandle(String masterId, String masterHomeId) {
        AppUserHomeRelationDO appUserHomeRelationDo = appUserHomeRelationDao.selectOne(Wrappers.<AppUserHomeRelationDO>lambdaQuery()
                .eq(AppUserHomeRelationDO::getAppUserId, masterId).eq(AppUserHomeRelationDO::getHomeId, masterHomeId)
                .eq(AppUserHomeRelationDO::getRelationType, "0"));
        if (appUserHomeRelationDo == null) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "该家庭不是您账号下的家庭，无法操作");
        }
        return appUserHomeRelationDo;
    }

    /**
     * 确认分享了主人的家庭
     *
     * @param masterHomeId
     * @param childId
     */
    private void confirmShareMasterHomeToChildAccountSuccess(String masterHomeId, String childId) {
        AppUserHomeRelationDO relation = new AppUserHomeRelationDO();
        relation.setAppUserId(childId);
        relation.setHomeId(masterHomeId);
        relation.setRelationType(UserConstant.AppUserHomeRelation.SHARE);
        boolean confirm = save(relation);
        if (!confirm) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "新增子账号失败！");
        }
    }


    /**
     * 检查是否未注册
     *
     * @param account
     * @param organizationCode
     * @return
     */
    private AppUserDO checkAccountIsRegister(String account, String organizationCode) {
        AppUserDO childMessage = appUserHomeRelationDao.getAccountMessage(account, organizationCode);
        if (childMessage == null) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), account + "未注册请先注册！");
        }
        return childMessage;
    }

    /**
     * 删除分享关系
     *
     * @param userId
     * @param homeId
     */
    private void removeShareRelation(String userId, String homeId) {
        int count = appUserHomeRelationDao.deleteRelation(userId, homeId, UserConstant.AppUserHomeRelation.SHARE);
        if (count < 1) {
            throw new ZyServerException(ErrorType.Service_Fail);
        }
    }


    /**
     * 给子账号发送已经分享的推送
     *
     * @param masterName     主人的名称
     * @param masterHomeName 主人分享的家庭的名称
     * @param masterHomeId   主人的家庭ID
     * @param childPushId    子账号的推送ID
     * @param childId        子账号的ID
     * @param childPhoneType 子账号的手机类型
     * @param appOrgCode     子账号的组织编码
     */
    private void shareHomeJpushToChildAccount(String masterName, String masterHomeName, String masterHomeId, String childPushId,
                                              String childId, String childPhoneType, String appOrgCode) {

        String message = masterName + "分享了" + masterHomeName + "给您";
        // 推送
        try {
            jPushService.send(MessageCode.JPUSH_TITLE, message, MessageCode.ACCOUNT_TYPE,
                    childPushId, ExtrasCode.IN_SHARE, masterHomeId, childId, childPhoneType, appOrgCode);
        } catch (Exception e) {
            log.warn("分享家庭推送发送失败,masterName:{},masterHomeName:{},childId:{},appOrgCode:{}", masterName, masterHomeName, childId, appOrgCode);
        }

    }

    /***
     * 只有一个家庭无法进行转移
     * @param masterId
     */
    private void onlyOneHomeCanNotTransfer(String masterId) {
        // 判断是否有两个或以上家庭
        int homeCount = appUserHomeRelationDao.selectCountByAppUserId(masterId);
        if (homeCount <= 1) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "请保证有两个或以上家庭再转移");
        }
    }

    /**
     * 转移摄像头
     *
     * @param childId
     * @param masterHomeId
     */
    private void transferEz(String childId, String masterHomeId) {
        EzvizTokenDO ezvizTokenDO = new EzvizTokenDO();
        ezvizTokenDO.setAppUserId(childId);
        ezvizTokenDao.update(ezvizTokenDO, Wrappers.<EzvizTokenDO>lambdaQuery().eq(EzvizTokenDO::getHomeId, masterHomeId));
    }


    /**
     * 取消分享推送
     *
     * @param childMessage
     * @param homeId
     * @param childAccount
     * @param orgCode
     * @param masterOrSelf
     */
    private void cancelShareJpush(AppUserDO childMessage, String homeId, String childAccount, String orgCode, String masterOrSelf) {
        // 通过家庭id获得家庭名称
        String homeName = appUserHomeRelationDao.getHomeNameById(homeId);
        try {
            //主人取消，把消息发给对象
            if (MASTER_CANCEL_SHARE.equals(masterOrSelf.trim())) {
                jPushService.send(MessageCode.JPUSH_TITLE, homeName + "的家庭已取消分享",
                        MessageCode.ACCOUNT_TYPE, childMessage.getSourceId(), ExtrasCode.OUT_SHARE,
                        homeId, childMessage.getId(), childMessage.getSourceType() + "", orgCode);

            }
            //自己取消，把消息发送给主人
            else if (CHILD_ACCOUNT_CANCEL_SHARE.equals(masterOrSelf.trim())) {
                AppUserDO appUserDO = appUserHomeRelationDao.getMasterSourceId(homeId);
                jPushService.send(MessageCode.JPUSH_TITLE, "用户" + childAccount + "已经取消了您分享的家庭：" + homeName,
                        MessageCode.ACCOUNT_TYPE, appUserDO.getSourceId(), ExtrasCode.OUT_SHARE_SELF,
                        homeId, appUserDO.getId() + "", appUserDO.getSourceType().toString(), appUserDO.getOrganizationCode());
            }
        } catch (Exception e) {
            log.warn("取消分享家庭推送发送失败:homeId:{},childAccount:{},masterOrSelf{}", homeId, childAccount, masterOrSelf);
        }

    }

    /**
     * 转移家庭推送
     *
     * @param childMessage
     * @param relation
     */
    private void transferHomeJpush(AppUserDO childMessage, AppUserHomeRelationDO relation) {
        String homeName = appUserHomeRelationDao.getHomeNameById(relation.getHomeId());
        String masterName = appUserHomeRelationDao.getUserName(relation.getAppUserId());
        try {
            jPushService.send(MessageCode.JPUSH_TITLE, masterName + "转移了" + homeName + "给您", MessageCode.ACCOUNT_TYPE,
                    childMessage.getSourceId(), ExtrasCode.IN_SHARE, "", childMessage.getId() + "",
                    childMessage.getSourceType() + "", childMessage.getOrganizationCode());
        } catch (Exception e) {
            log.warn("转移家庭推送发送失败:homeId:{},childAccount:{}", relation.getHomeId(), childMessage.getAccount());
        }

    }


    /**
     * 获取子账号列表
     *
     * @param homeId
     * @return
     */
    public List<ChildAccountMessageRepDTO> getChildUserList(String homeId) {
        List<AppUserDO> appUserDoS = appUserHomeRelationDao.selectChildUserList(homeId);
        if (CollectionUtils.isEmpty(appUserDoS)) {
            return Collections.emptyList();
        }
        List<ChildAccountMessageRepDTO> childAccountMessageRepDtos = new ArrayList<>(5);
        appUserDoS.forEach(list -> {
            ChildAccountMessageRepDTO childAccountMessageRepDTO = new ChildAccountMessageRepDTO().appUserDoToChildDto(list);
            childAccountMessageRepDtos.add(childAccountMessageRepDTO);
        });
        return childAccountMessageRepDtos;
    }
}
